package com.tyc.aspect;

import com.alibaba.fastjson.JSONObject;
import com.tyc.annotation.Limiter;
import com.tyc.utill.IpUtil;
import com.tyc.utill.RedisLimit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;

/**
 * 类描述
 *
 * @author tyc
 * @version 1.0
 * @date 2023-02-20 16:06:17
 */
@Aspect
@Component
@Slf4j
public class LimitAspect {
    @Autowired
    private RedisLimit redisLimit;

    @Autowired
    private HttpServletResponse response;

    @Pointcut("@annotation(com.tyc.annotation.Limiter)")
    public void pointcut(){
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Limiter limiter = method.getAnnotation(Limiter.class);
        // 获取每秒限制次数
        int limitTimesSecond = limiter.value();
        HttpServletRequest request = getHttpServletRequest();
        String flag = redisLimit.limit(IpUtil.getIpAddr(request), limitTimesSecond);
        if("0".equals(flag)){
            // 触发限流
            fullBack();
            return null;
        }
        return joinPoint.proceed();
    }

    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        return servletRequestAttributes.getRequest();
    }

    /**
     * 触发限流处理
     */
    private void fullBack(){
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Cache-Control", "no-cache");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code","-1");
            jsonObject.put("msg","系统繁忙");
            writer.println(jsonObject.toJSONString());
            writer.flush();
        } catch (IOException e) {
            log.error("fullBack error:{}",e.getMessage());
        }finally {
            writer.close();
        }
    }
}
